package code.ws_common_scene
{
	import code.ws_common_ems.ModeActionEms;
	import code.ws_common_ems.ModeRenderEms;
	import code.ws_common_ems.ModeStatusEms;
	import code.ws_common_interface.SerManager;
	import code.ws_common_scene.astar.AStar;
	import code.ws_common_scene.eft.Effects;
	import code.ws_common_scene.manager.SceneArticleManager;
	import code.ws_common_scene.manager.SceneManager;
	import code.ws_common_scene.map.MapData;
	import code.ws_common_scene.map.MapModePool;
	import code.ws_common_scene.map.MapSlice;
	import code.ws_common_scene.map.XMapMode;
	import code.ws_common_scene.mode.Hero;
	import code.ws_common_scene.mode.Trans;
	import code.ws_common_utils.EnterFrameUtils;
	import code.ws_common_utils.IDUtils;
	import code.ws_common_utils.LayerUtils;
	import code.ws_common_utils.SysUtils;
	import code.ws_common_utils.UrlUtils;
	
	import flash.display.BitmapData;
	import flash.geom.Point;
	import flash.utils.Dictionary;
	
	import je.engine.loaderware.realtimeLoa.JERTLoaMain;
	
	import starling.core.Starling;
	import starling.display.DisplayObject;
	import starling.display.Sprite;

	/**
	 * 主场景 
	 * @author qiangchen
	 * 
	 */	
	public class GameScene extends Sprite
	{
		/** astar寻路器 */
		private var _astar:AStar = null;
		/** 地图id */
		private var mapid:String = null;
		/** 地图数据 */
		private var _mapData:MapData = null;
		/** 地图模型 */
		private var _mapMode:XMapMode = null;
		/** 地图纹理切片处理工具 */
		private var _mapSlice:MapSlice = null;
		/** 艺术演员容器 */
		public var _articleCons:Sprite = null;
		/** 英雄 */
		private var _player:Hero = null;
		/** 英雄在进入场景的位置 */
		private var _enterScenePos:Point=null;
		/** 特效池 */
		private var _eftDic:Dictionary = new Dictionary();
		/** 显示对象池(同屏的) */
		public var _eyeDic:Dictionary = new Dictionary();
		/** 表演者容器进行深度排序的时间间隔累加器 */
		private var depth_t:int;
		
		/**
		 * 构造函数 
		 * 
		 */		
		public function GameScene()
		{
			// 注册刷新方法
			EnterFrameUtils.add( "scene", refresh );
			
			// 初始化astar寻路器
			_astar = new AStar();
			
			// 初始化地图切片处理工具
			_mapSlice = new MapSlice();
			addChild( _mapSlice );
			
			// 演员容器
			_articleCons = new Sprite();
			_articleCons.touchable = true;
			addChild( _articleCons );
		}
		
		/*-------------------------------场景初始化，创建----------------------------------*/
		
		
		/**
		 * 进入地图，并初始化地图数据以及地图切片
		 * @param mapId 地图id
		 */		
		public function enterMap( mapId:String ):void
		{
			if( mapId == null || mapId == "" )
			{
				throw new Error( "[GameScene]--->(Error): initer map was error! mapId is null or \"\". " );
				return;
			}
			mapid = mapId;
			
			// 退出当前地图时进行清理
			quitMap();
			
			LayerUtils.interlude.visible = true;
			
			//...初始化地图数据
			if( !_mapData ) 
			{	
				_mapData = new MapData();
			}
			_mapData.build( mapId );
			
			//...加载地图资源
			_mapMode = MapModePool.getMapMode( mapid );
			if( _mapMode._hasLoader )
			{
				// 已经加载过
				JERTLoaMain.startLoa( [ UrlUtils.getMicroMapUrl(mapId), UrlUtils.getOriginalMapUrl( mapId )], null, mapResLoaCom, mapResLoaPro );
			}
			else
			{
				// 未加载
				JERTLoaMain.startLoa( _mapMode._mapReses.concat( UrlUtils.getMicroMapUrl(mapId), UrlUtils.getOriginalMapUrl( mapId ) ), null, mapResLoaCom, mapResLoaPro );
			}
			SerManager.instance.interludeLoginSer.setProgressInfo( "Scene initialization..." );
		}
		
		/**
		 * 场景资源加载过程 
		 * @param val
		 * @param obj
		 */		
		private function mapResLoaPro( val:Number, obj:Object ):void
		{
			SerManager.instance.interludeLoginSer.setProgerssVal( val );
			if( val == 1 )
			{
				//...处理地图切片，并进行显示
				_mapSlice.analyze( obj as BitmapData );
			}
		}
		
		
		/**
		 * 场景资源加载完毕
		 * 
		 */		
		private function mapResLoaCom():void
		{
			_mapMode._hasLoader = true;
			
			// 创建传送阵
			SceneArticleManager.instance.cTrans( _mapMode, mapData );
			// 初始化角色
			cHero();
			// 创建怪物
			SceneArticleManager.instance.cMonsters( mapId, mapData );
		
			LayerUtils.interlude.visible = false;
			SceneManager.instance.sceneTouchFlag( true );
			_mapMode = null;
			trace("【ws_mobile】---> enter scene! map id is : " + mapId);
		}
		
		private function cHero():void
		{
			if( !_player )
			{
				_player = new Hero( ModeRenderEms.HERO, "mry", ModeActionEms.STAND, 3 );
				_player.setStatus( ModeStatusEms.STAND );
				_player.setName( "★ Jonathan Qiang" );
				_player.setMoveSpeed( 190 );
				_player.power = 100;
				_player.maxHp = -1;
				_player.hp = _player.maxHp;
				_articleCons.addChild( _player );
			}
			
			_player.showid = IDUtils.SELF_ID;
			_player.tiles = _enterScenePos;
			_player.setDirection( _player.direction );
			_player.x = _player.tiles.x * mapData.tileW + mapData.hTileW;
			_player.y = _player.tiles.y * mapData.tileH + mapData.hTileH;
			
			// 滚动地图
			scrollMap( _player.x, _player.y );
		}
		
		/*---------------------------------------End--------------------------------------*/
		
		/**
		 * 登出地图, 销毁当前登出地图的数据以及地图切片 .
		 * 
		 */		
		public function quitMap():void
		{
			SceneManager.instance.sceneTouchFlag( false );
			SceneManager.instance.crtAttackid = IDUtils.INVALID_ID;
			SceneManager.instance.crtSelectid = IDUtils.INVALID_ID;
			SceneManager.instance.prevSelectid = IDUtils.INVALID_ID;
			
			// 释放过场加载器
			JERTLoaMain.dispose();
			
			// 重置地图切片
			_mapSlice && _mapSlice.reset();
			_mapMode = null;
			
			if( _player )
			{
				_player.stand();
				Starling.juggler.removeTweens( _player );
			}
			
			for each( var e:Effects in _eftDic )
			{
				if( e )
				{
					delEffect( e.name );
				}
			}
			
			for ( var ids:String in _eyeDic )
			{
				if( !_eyeDic[ids] ) continue;
				
				Starling.juggler.removeTweens( _eyeDic[ids] );
				IDUtils.dId( int(ids) );
				
				_eyeDic[ids].dispose();
				_eyeDic[ids].parent && _eyeDic[ids].parent.removeChild( _eyeDic[ids], true );
				_eyeDic[ids] = null;
				delete _eyeDic[ids];
			}
		}
		
		
		
		/**
		 * 寻路（获取路径） 
		 * @param sp 起始点（逻辑网格点）
		 * @param ep 目标点（逻辑网格点）
		 * @return 路径
		 */		
		public function findPath( sp:Point, ep:Point ):Array
		{
			if( sp == null || ep == null )
			{
				return null;
			}
			if( _astar )
			{
				if( mapData == null )
				{
					return null;
				}
				else
				{
					return _astar.find( sp.x, sp.y, ep.x, ep.y, mapData );
				}
			}
			return null;
		}
		
		
		
		/**
		 * 滚动地图 
		 * @param _x 角色当前的x轴位置（像素点）
		 * @param _y 角色当前的y轴位置（像素点）
		 * 
		 */		
		public function scrollMap( _x:Number, _y:Number ):void
		{
			var focus_p:Point = getFocusPoint( _x >> 0, _y >> 0 );
			if( !focus_p )
			{
				return;
			}
			
//			var _scrollRect:Rectangle = new Rectangle();
//			_scrollRect.x = focus_p.x;
//			_scrollRect.y = focus_p.y;
//			_scrollRect.width = SysUtils.stage.stageWidth;
//			_scrollRect.height = SysUtils.stage.stageHeight;
//			this.clipRect = _scrollRect;
			this.x = -focus_p.x;
			this.y = -focus_p.y;
			focus_p = null;
//			_scrollRect = null;
		}
		
		/**
		 * 根据角色移动的位置确定场景位置 
		 * @param _x
		 * @param _y
		 * @return 
		 * 
		 */		
		private function getFocusPoint( _x:Number, _y:Number ):Point
		{
			var crtStgW:Number = SysUtils.stage.stageWidth;
			var crtStgH:Number = SysUtils.stage.stageHeight;
			var rect_p:Point = new Point();
			
			// Point - x;
			if( _x < ( crtStgW >> 1 ) )
			{
				rect_p.x = 0;
			}
			else if( _x > ( mapData.mapW - ( crtStgW >> 1 ) ) )
			{
				rect_p.x = mapData.mapW - crtStgW;
			}
			else
			{
				rect_p.x = _x - ( crtStgW >> 1 );
			}
			
			// Point - y;
			if( _y < ( crtStgH >> 1 ) )
			{
				rect_p.y = 0;
			}
			else if( _y > ( mapData.mapH - ( crtStgH >> 1 ) ) )
			{
				rect_p.y = mapData.mapH - crtStgH;
			}
			else
			{
				rect_p.y = _y - ( crtStgH >> 1 );
			}
			
			crtStgH = crtStgW = NaN;
			return rect_p;
		}
		
		
		/**
		 * 添加特效
		 * @param eid 特效id
		 * @param e 特效对象
		 * @param point 位置
		 * @param isExit 是否运行一次流程后释放 （默认：true，释放）
		 */		
		public function addEffect( eid:String, e:Effects, point:Point, isExit:Boolean=true ):void
		{
			if( _eftDic[eid] ) 
			{
				delEffect( eid );
			}
			
			e.name = eid;
			_eftDic[e.name] = e;
			addChild( _eftDic[e.name] );
			e.x = point.x;
			e.y = point.y;
			if( isExit )
			{
				Starling.juggler.tween( e, e.playData.totalTime/1000, {onComplete:delEffect, onCompleteArgs:[eid]});
			}
		}
		
		
		/**
		 * 删除特效 
		 * @param eid
		 * 
		 */		
		public function delEffect( eid:String ):void
		{
			if( !_eftDic[eid] ) return;
			
			Starling.juggler.removeTweens( _eftDic[eid] );
			_eftDic[eid] .dispose();
			
			_eftDic[eid].parent && _eftDic[eid].parent.removeChild( _eftDic[eid], true );
			_eftDic[eid] = null;
			
			delete _eftDic[eid];
		}
		
		
		/**
		 * 视野范围内的场景显示对象深度排序 
		 * 
		 */		
		private function sortDisplayobjDepth():void
		{
			// 排序组
			var sorts:Array = [];
			var dis:DisplayObject;
			var transNum:int=0;
			for ( var s:int=0; s<_articleCons.numChildren; s++ )
			{
				dis = _articleCons.getChildAt( s );
				if( dis is Trans )
				{
					transNum ++;
					continue;
				}
				sorts.push( dis );
			}
			sorts.sortOn( "y", Array.NUMERIC );
			
			// 排序
			var i:int;
			var reali:int;
			var len:int = sorts.length - 1;
			while( i <= len )
			{
				dis = sorts[i];
				reali = i + transNum;
				if( reali != _articleCons.getChildIndex( dis ) )
				{
					_articleCons.setChildIndex( dis, reali );
				}
				i++;
			}
			
			sorts.length = 0;
			sorts = null;
			dis = null;
			transNum = reali = i = len = NaN;
		}
	
		
		/** 震屏幕开关 */
		public var _vsFlag:Boolean = false;
		/** 记录震屏前的场景位置 */
		public var orgY:Number;
		/** sin函数的角度 */
		private var r:Number = 0;
		/** sin函数角度累加值 */
		private const ra:Number = 10;
		/** 振幅 */
		private const a:Number = 5;
		/**
		 * 震屏 
		 * 
		 */		
		private function vibrationScreen():void
		{
			if( !_vsFlag ) return;

			this.y += Math.sin( r ) * a * -1;
			r += ra;
			if( r >= 100 )
			{
				this.y = orgY;
				orgY = NaN;
				r = 0;
				_vsFlag = false;
			}
 		}
		
		
		
		/**
		 * 场景物件刷新 
		 * 
		 */		
		public function refresh():void
		{
			if( _player )
			{
				_player.refresh();
			}
			
			for each( var e:Effects in _eftDic )
			{
				e && e.refresh();
			}
			
			for each( var dis:Object in _eyeDic )
			{
				dis && dis.refresh();
			}
			
			// 场景表演者深度排序
			if( depth_t > 10 )
			{
				depth_t = 0;
				sortDisplayobjDepth();
			}
			depth_t ++;
			
			// 震屏
			vibrationScreen();
		}
		
		
		
		/**
		 * 获取英雄对象 
		 * @return 
		 * 
		 */		
		public function get hero():Hero
		{
			return _player;
		}
		
		
		/**
		 * 英雄进入场景的位置 
		 * @param p
		 * 
		 */		
		public function setEnterMapPos( p:Point ):void
		{
			_enterScenePos = p;
		}
		
		/**
		 * 获取地图id 
		 * @return 
		 * 
		 */		
		public function get mapId():String
		{
			return mapid;
		}
		
		
		/**
		 * 获取地图数据 
		 * @return 
		 * 
		 */		
		public function get mapData():MapData
		{
			return _mapData;
		}
		
		
		/**
		 * 释放 
		 * 
		 */		
		override public function dispose():void
		{
			JERTLoaMain.dispose();
			
			_astar = null;
			mapid = null;
			_mapMode = null;
			_mapData.die();
			_mapData = null;
			
			_mapSlice.dispose();
			_mapSlice.parent && _mapSlice.parent.removeChild( _mapSlice, true );
			_mapSlice = null;
			
			_player.dispose();
			_player.parent && _player.parent.removeChild( _player, true );
			_player = null;
			_enterScenePos = null;
			
			for each( var e:Effects in _eftDic )
			{
				if( e )
				{
					delEffect( e.name );
				}
			}
			_eftDic = null;
			
			for ( var ids:String in _eyeDic )
			{
				Starling.juggler.removeTweens( _eyeDic[ids] );
				IDUtils.dId( int(ids) );
				
				_eyeDic[ids].dispose();
				_eyeDic[ids].parent && _eyeDic[ids].parent.removeChild( _eyeDic[ids], true );
				_eyeDic[ids] = null;
				delete _eyeDic[ids];
			}
			_eyeDic = null;
			
			_articleCons.parent && _articleCons.parent.removeChild( _articleCons, true );
			_articleCons = null;
			
			depth_t = NaN;
			super.dispose();
		}
	}
}